package tools.jackson.module.kotlin.kogeraIntegration.deser.valueClass.parameterSize.nonNullObject

import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import tools.jackson.module.kotlin.assertReflectEquals
import tools.jackson.module.kotlin.callPrimaryConstructor
import tools.jackson.module.kotlin.defaultMapper
import tools.jackson.module.kotlin.kogeraIntegration.deser.valueClass.NonNullObject
import tools.jackson.module.kotlin.readValue

/**
 * Up to argument size 32 there is one mask argument for the default argument,
 * 33 ~ 64 there are two, and 65 there are three, so each boundary value is tested.
 * Also, the maximum size of arguments that can be set by a constructor
 * that includes a value class as an argument is 253 (one less by DefaultConstructorMarker), so test that case as well.
 */
class DeserializeByConstructorWithoutDefaultArgumentsTest {
    data class Dst32(
        val p00: NonNullObject,
        val p01: NonNullObject,
        val p02: NonNullObject,
        val p03: NonNullObject,
        val p04: NonNullObject,
        val p05: NonNullObject,
        val p06: NonNullObject,
        val p07: NonNullObject,
        val p08: NonNullObject,
        val p09: NonNullObject,
        val p10: NonNullObject,
        val p11: NonNullObject,
        val p12: NonNullObject,
        val p13: NonNullObject,
        val p14: NonNullObject,
        val p15: NonNullObject,
        val p16: NonNullObject,
        val p17: NonNullObject,
        val p18: NonNullObject,
        val p19: NonNullObject,
        val p20: NonNullObject,
        val p21: NonNullObject,
        val p22: NonNullObject,
        val p23: NonNullObject,
        val p24: NonNullObject,
        val p25: NonNullObject,
        val p26: NonNullObject,
        val p27: NonNullObject,
        val p28: NonNullObject,
        val p29: NonNullObject,
        val p30: NonNullObject,
        val p31: NonNullObject
    )

    @Test
    fun test32() {
        val expected = callPrimaryConstructor<Dst32> { NonNullObject(it.name!!) }
        val src = defaultMapper.writeValueAsString(expected)
        assertEquals(expected, defaultMapper.readValue<Dst32>(src))
    }

    data class Dst33(
        val p00: NonNullObject,
        val p01: NonNullObject,
        val p02: NonNullObject,
        val p03: NonNullObject,
        val p04: NonNullObject,
        val p05: NonNullObject,
        val p06: NonNullObject,
        val p07: NonNullObject,
        val p08: NonNullObject,
        val p09: NonNullObject,
        val p10: NonNullObject,
        val p11: NonNullObject,
        val p12: NonNullObject,
        val p13: NonNullObject,
        val p14: NonNullObject,
        val p15: NonNullObject,
        val p16: NonNullObject,
        val p17: NonNullObject,
        val p18: NonNullObject,
        val p19: NonNullObject,
        val p20: NonNullObject,
        val p21: NonNullObject,
        val p22: NonNullObject,
        val p23: NonNullObject,
        val p24: NonNullObject,
        val p25: NonNullObject,
        val p26: NonNullObject,
        val p27: NonNullObject,
        val p28: NonNullObject,
        val p29: NonNullObject,
        val p30: NonNullObject,
        val p31: NonNullObject,
        val p32: NonNullObject
    )

    @Test
    fun test33() {
        val expected = callPrimaryConstructor<Dst33> { NonNullObject(it.name!!) }
        val src = defaultMapper.writeValueAsString(expected)
        assertEquals(expected, defaultMapper.readValue<Dst33>(src))
    }

    data class Dst64(
        val p00: NonNullObject,
        val p01: NonNullObject,
        val p02: NonNullObject,
        val p03: NonNullObject,
        val p04: NonNullObject,
        val p05: NonNullObject,
        val p06: NonNullObject,
        val p07: NonNullObject,
        val p08: NonNullObject,
        val p09: NonNullObject,
        val p10: NonNullObject,
        val p11: NonNullObject,
        val p12: NonNullObject,
        val p13: NonNullObject,
        val p14: NonNullObject,
        val p15: NonNullObject,
        val p16: NonNullObject,
        val p17: NonNullObject,
        val p18: NonNullObject,
        val p19: NonNullObject,
        val p20: NonNullObject,
        val p21: NonNullObject,
        val p22: NonNullObject,
        val p23: NonNullObject,
        val p24: NonNullObject,
        val p25: NonNullObject,
        val p26: NonNullObject,
        val p27: NonNullObject,
        val p28: NonNullObject,
        val p29: NonNullObject,
        val p30: NonNullObject,
        val p31: NonNullObject,
        val p32: NonNullObject,
        val p33: NonNullObject,
        val p34: NonNullObject,
        val p35: NonNullObject,
        val p36: NonNullObject,
        val p37: NonNullObject,
        val p38: NonNullObject,
        val p39: NonNullObject,
        val p40: NonNullObject,
        val p41: NonNullObject,
        val p42: NonNullObject,
        val p43: NonNullObject,
        val p44: NonNullObject,
        val p45: NonNullObject,
        val p46: NonNullObject,
        val p47: NonNullObject,
        val p48: NonNullObject,
        val p49: NonNullObject,
        val p50: NonNullObject,
        val p51: NonNullObject,
        val p52: NonNullObject,
        val p53: NonNullObject,
        val p54: NonNullObject,
        val p55: NonNullObject,
        val p56: NonNullObject,
        val p57: NonNullObject,
        val p58: NonNullObject,
        val p59: NonNullObject,
        val p60: NonNullObject,
        val p61: NonNullObject,
        val p62: NonNullObject,
        val p63: NonNullObject
    )

    @Test
    fun test64() {
        val expected = callPrimaryConstructor<Dst64> { NonNullObject(it.name!!) }
        val src = defaultMapper.writeValueAsString(expected)
        assertEquals(expected, defaultMapper.readValue<Dst64>(src))
    }

    data class Dst65(
        val p00: NonNullObject,
        val p01: NonNullObject,
        val p02: NonNullObject,
        val p03: NonNullObject,
        val p04: NonNullObject,
        val p05: NonNullObject,
        val p06: NonNullObject,
        val p07: NonNullObject,
        val p08: NonNullObject,
        val p09: NonNullObject,
        val p10: NonNullObject,
        val p11: NonNullObject,
        val p12: NonNullObject,
        val p13: NonNullObject,
        val p14: NonNullObject,
        val p15: NonNullObject,
        val p16: NonNullObject,
        val p17: NonNullObject,
        val p18: NonNullObject,
        val p19: NonNullObject,
        val p20: NonNullObject,
        val p21: NonNullObject,
        val p22: NonNullObject,
        val p23: NonNullObject,
        val p24: NonNullObject,
        val p25: NonNullObject,
        val p26: NonNullObject,
        val p27: NonNullObject,
        val p28: NonNullObject,
        val p29: NonNullObject,
        val p30: NonNullObject,
        val p31: NonNullObject,
        val p32: NonNullObject,
        val p33: NonNullObject,
        val p34: NonNullObject,
        val p35: NonNullObject,
        val p36: NonNullObject,
        val p37: NonNullObject,
        val p38: NonNullObject,
        val p39: NonNullObject,
        val p40: NonNullObject,
        val p41: NonNullObject,
        val p42: NonNullObject,
        val p43: NonNullObject,
        val p44: NonNullObject,
        val p45: NonNullObject,
        val p46: NonNullObject,
        val p47: NonNullObject,
        val p48: NonNullObject,
        val p49: NonNullObject,
        val p50: NonNullObject,
        val p51: NonNullObject,
        val p52: NonNullObject,
        val p53: NonNullObject,
        val p54: NonNullObject,
        val p55: NonNullObject,
        val p56: NonNullObject,
        val p57: NonNullObject,
        val p58: NonNullObject,
        val p59: NonNullObject,
        val p60: NonNullObject,
        val p61: NonNullObject,
        val p62: NonNullObject,
        val p63: NonNullObject,
        val p64: NonNullObject
    )

    @Test
    fun test65() {
        val expected = callPrimaryConstructor<Dst65> { NonNullObject(it.name!!) }
        val src = defaultMapper.writeValueAsString(expected)
        assertEquals(expected, defaultMapper.readValue<Dst65>(src))
    }

    // It cannot be a data class because the generated method would exceed the argument size limit.
    class DstMax(
        val p000: NonNullObject,
        val p001: NonNullObject,
        val p002: NonNullObject,
        val p003: NonNullObject,
        val p004: NonNullObject,
        val p005: NonNullObject,
        val p006: NonNullObject,
        val p007: NonNullObject,
        val p008: NonNullObject,
        val p009: NonNullObject,
        val p010: NonNullObject,
        val p011: NonNullObject,
        val p012: NonNullObject,
        val p013: NonNullObject,
        val p014: NonNullObject,
        val p015: NonNullObject,
        val p016: NonNullObject,
        val p017: NonNullObject,
        val p018: NonNullObject,
        val p019: NonNullObject,
        val p020: NonNullObject,
        val p021: NonNullObject,
        val p022: NonNullObject,
        val p023: NonNullObject,
        val p024: NonNullObject,
        val p025: NonNullObject,
        val p026: NonNullObject,
        val p027: NonNullObject,
        val p028: NonNullObject,
        val p029: NonNullObject,
        val p030: NonNullObject,
        val p031: NonNullObject,
        val p032: NonNullObject,
        val p033: NonNullObject,
        val p034: NonNullObject,
        val p035: NonNullObject,
        val p036: NonNullObject,
        val p037: NonNullObject,
        val p038: NonNullObject,
        val p039: NonNullObject,
        val p040: NonNullObject,
        val p041: NonNullObject,
        val p042: NonNullObject,
        val p043: NonNullObject,
        val p044: NonNullObject,
        val p045: NonNullObject,
        val p046: NonNullObject,
        val p047: NonNullObject,
        val p048: NonNullObject,
        val p049: NonNullObject,
        val p050: NonNullObject,
        val p051: NonNullObject,
        val p052: NonNullObject,
        val p053: NonNullObject,
        val p054: NonNullObject,
        val p055: NonNullObject,
        val p056: NonNullObject,
        val p057: NonNullObject,
        val p058: NonNullObject,
        val p059: NonNullObject,
        val p060: NonNullObject,
        val p061: NonNullObject,
        val p062: NonNullObject,
        val p063: NonNullObject,
        val p064: NonNullObject,
        val p065: NonNullObject,
        val p066: NonNullObject,
        val p067: NonNullObject,
        val p068: NonNullObject,
        val p069: NonNullObject,
        val p070: NonNullObject,
        val p071: NonNullObject,
        val p072: NonNullObject,
        val p073: NonNullObject,
        val p074: NonNullObject,
        val p075: NonNullObject,
        val p076: NonNullObject,
        val p077: NonNullObject,
        val p078: NonNullObject,
        val p079: NonNullObject,
        val p080: NonNullObject,
        val p081: NonNullObject,
        val p082: NonNullObject,
        val p083: NonNullObject,
        val p084: NonNullObject,
        val p085: NonNullObject,
        val p086: NonNullObject,
        val p087: NonNullObject,
        val p088: NonNullObject,
        val p089: NonNullObject,
        val p090: NonNullObject,
        val p091: NonNullObject,
        val p092: NonNullObject,
        val p093: NonNullObject,
        val p094: NonNullObject,
        val p095: NonNullObject,
        val p096: NonNullObject,
        val p097: NonNullObject,
        val p098: NonNullObject,
        val p099: NonNullObject,
        val p100: NonNullObject,
        val p101: NonNullObject,
        val p102: NonNullObject,
        val p103: NonNullObject,
        val p104: NonNullObject,
        val p105: NonNullObject,
        val p106: NonNullObject,
        val p107: NonNullObject,
        val p108: NonNullObject,
        val p109: NonNullObject,
        val p110: NonNullObject,
        val p111: NonNullObject,
        val p112: NonNullObject,
        val p113: NonNullObject,
        val p114: NonNullObject,
        val p115: NonNullObject,
        val p116: NonNullObject,
        val p117: NonNullObject,
        val p118: NonNullObject,
        val p119: NonNullObject,
        val p120: NonNullObject,
        val p121: NonNullObject,
        val p122: NonNullObject,
        val p123: NonNullObject,
        val p124: NonNullObject,
        val p125: NonNullObject,
        val p126: NonNullObject,
        val p127: NonNullObject,
        val p128: NonNullObject,
        val p129: NonNullObject,
        val p130: NonNullObject,
        val p131: NonNullObject,
        val p132: NonNullObject,
        val p133: NonNullObject,
        val p134: NonNullObject,
        val p135: NonNullObject,
        val p136: NonNullObject,
        val p137: NonNullObject,
        val p138: NonNullObject,
        val p139: NonNullObject,
        val p140: NonNullObject,
        val p141: NonNullObject,
        val p142: NonNullObject,
        val p143: NonNullObject,
        val p144: NonNullObject,
        val p145: NonNullObject,
        val p146: NonNullObject,
        val p147: NonNullObject,
        val p148: NonNullObject,
        val p149: NonNullObject,
        val p150: NonNullObject,
        val p151: NonNullObject,
        val p152: NonNullObject,
        val p153: NonNullObject,
        val p154: NonNullObject,
        val p155: NonNullObject,
        val p156: NonNullObject,
        val p157: NonNullObject,
        val p158: NonNullObject,
        val p159: NonNullObject,
        val p160: NonNullObject,
        val p161: NonNullObject,
        val p162: NonNullObject,
        val p163: NonNullObject,
        val p164: NonNullObject,
        val p165: NonNullObject,
        val p166: NonNullObject,
        val p167: NonNullObject,
        val p168: NonNullObject,
        val p169: NonNullObject,
        val p170: NonNullObject,
        val p171: NonNullObject,
        val p172: NonNullObject,
        val p173: NonNullObject,
        val p174: NonNullObject,
        val p175: NonNullObject,
        val p176: NonNullObject,
        val p177: NonNullObject,
        val p178: NonNullObject,
        val p179: NonNullObject,
        val p180: NonNullObject,
        val p181: NonNullObject,
        val p182: NonNullObject,
        val p183: NonNullObject,
        val p184: NonNullObject,
        val p185: NonNullObject,
        val p186: NonNullObject,
        val p187: NonNullObject,
        val p188: NonNullObject,
        val p189: NonNullObject,
        val p190: NonNullObject,
        val p191: NonNullObject,
        val p192: NonNullObject,
        val p193: NonNullObject,
        val p194: NonNullObject,
        val p195: NonNullObject,
        val p196: NonNullObject,
        val p197: NonNullObject,
        val p198: NonNullObject,
        val p199: NonNullObject,
        val p200: NonNullObject,
        val p201: NonNullObject,
        val p202: NonNullObject,
        val p203: NonNullObject,
        val p204: NonNullObject,
        val p205: NonNullObject,
        val p206: NonNullObject,
        val p207: NonNullObject,
        val p208: NonNullObject,
        val p209: NonNullObject,
        val p210: NonNullObject,
        val p211: NonNullObject,
        val p212: NonNullObject,
        val p213: NonNullObject,
        val p214: NonNullObject,
        val p215: NonNullObject,
        val p216: NonNullObject,
        val p217: NonNullObject,
        val p218: NonNullObject,
        val p219: NonNullObject,
        val p220: NonNullObject,
        val p221: NonNullObject,
        val p222: NonNullObject,
        val p223: NonNullObject,
        val p224: NonNullObject,
        val p225: NonNullObject,
        val p226: NonNullObject,
        val p227: NonNullObject,
        val p228: NonNullObject,
        val p229: NonNullObject,
        val p230: NonNullObject,
        val p231: NonNullObject,
        val p232: NonNullObject,
        val p233: NonNullObject,
        val p234: NonNullObject,
        val p235: NonNullObject,
        val p236: NonNullObject,
        val p237: NonNullObject,
        val p238: NonNullObject,
        val p239: NonNullObject,
        val p240: NonNullObject,
        val p241: NonNullObject,
        val p242: NonNullObject,
        val p243: NonNullObject,
        val p244: NonNullObject,
        val p245: NonNullObject,
        val p246: NonNullObject,
        val p247: NonNullObject,
        val p248: NonNullObject,
        val p249: NonNullObject,
        val p250: NonNullObject,
        val p251: NonNullObject,
        val p252: NonNullObject
    )

    @Test
    fun testMax() {
        val expected = callPrimaryConstructor<DstMax> { NonNullObject(it.name!!) }
        val src = defaultMapper.writeValueAsString(expected)
        assertReflectEquals(expected, defaultMapper.readValue<DstMax>(src))
    }
}
